home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 11 / develop 11 code / The NetWork Project / NetWork Programmer's Stuff / NetWorkLookup.p < prev    next >
Encoding:
Text File  |  1992-07-15  |  14.7 KB  |  521 lines  |  [TEXT/MPS ]

  1. { Copyright 1989,90,91 The NetWork Project, StatLab Heidelberg.
  2.   Copyright 1989,90,91 Joachim Lindenberg, Karlsruhe,
  3.                        Günther Sawitzki, Heidelberg. All rights reserved. }
  4.  
  5. { This library does not support code without an A5 world. If you want to use
  6.   NetWork from other code (non application, non tool), you´ll have to use
  7.   control calls to the driver directly. Contact us if you need help with that.
  8.   
  9.   The library uses a call to NetWork Processor to find out whether this process
  10.   is already known to NetWork. If it is, it is assumed to be launched by NetWork
  11.   by means of a message or idle time launch, and the type and signature are confirmed.
  12.   If it is not known, the process is registered using the default type and the
  13.   application´s signature. The default type is pMaster unless you set pDefault to
  14.   something different. It is allowed to use pSlave or pLocal even if not launched
  15.   automatically, and the process will be subject to the rules of slave/local
  16.   processes in that case.
  17. }
  18.  
  19. {$IFC UNDEFINED UsingIncludes}
  20. {$SETC UsingIncludes := false}
  21. {$ENDC}
  22.  
  23. unit NetWorkLookup;
  24.  
  25. interface
  26.  
  27. { a star indicates that NetWork depends on these units, other comments indicate which unit
  28.   requires the inclusion of this unit. Tripple stars mark the units that are required
  29.   by the interface part of NetWork. If you use NetWork, but don´t use these units prior
  30.   to NetWork, NetWork will automatically include them. Note that conscious use of uses
  31.   will speed your compiles considerably. }
  32.  
  33. uses    Types {***}, FixMath {Packages}, QuickDraw {***lots of other units***},
  34.         Events {*}, OSUtils {***}, SegLoad {Files}, Files {Devices, StandardFile/Packages}, Devices {*},
  35.         Errors {*}, Memory {*}, Resources {*},
  36.         Packages {*}, SysEqu {*}, Traps {*},
  37.         ToolUtils {NetWorkLookup}, AppleTalk {NetWorkLookup},
  38.         NetWork;
  39.  
  40. {$IFC UNDEFINED UsingNetWorkLookup}
  41. {$SETC UsingNetWorkLookup:=true}
  42.  
  43. {$I+}
  44. {$SETC NetWorkLookupIncludes:=UsingIncludes}
  45. {$SETC UsingIncludes:=true}
  46.  
  47. {$IFC UNDEFINED UsingTypes}
  48. {$I $$SHELL(PInterfaces)Types.p}
  49. {$ENDC}
  50.  
  51. {$IFC UNDEFINED UsingOSUtils}
  52. {$I $$SHELL(PInterfaces)OSUtils.p}
  53. {$ENDC}
  54.  
  55. {$IFC UNDEFINED UsingAppletalk}
  56. {$I $$SHELL(PInterfaces)AppleTalk.p}
  57. {$ENDC}
  58.  
  59. {$IFC UNDEFINED UsingNetWorkUtilities}
  60. {$I $$SHELL(NetWorkIncludes)NetWorkUtilities.p}
  61. {$ENDC}
  62.  
  63. { use "pascal -d NlServer=false" if you don´t want to register your own names }
  64.  
  65. {$IFC Undefined NlServer}
  66. {$SETC NlServer:=true}
  67. {$ENDC}
  68.  
  69. { use "pascal -d NlClient=false" if you don´t want to look for other programs }
  70.  
  71. {$IFC Undefined NlClient}
  72. {$SETC NlClient:=true}
  73. {$ENDC}
  74.  
  75. {    =============================================================    }
  76.  
  77. {    name lookup - identication of possible partners }
  78.  
  79. const
  80.     nlVersion    = -31100;    { -- no appletalk version 48 or higher, could be removed }
  81.     nlTaskErr    = -31103;     { -- routines called in wrong order }
  82.     nlNotFound    = -31104;     { -- used internally }
  83.     nlDupReg    = -31105;     { -- called NlRegister twice }
  84.     nlNoReg        = -31106;     { -- called NlDeregister without NlRegister }
  85.     nlAtkOffErr = -31108;    { -- appletalk off, cannot use function }
  86.     
  87. function NlNode : longint;
  88.  
  89. {$IFC NlClient}
  90.  
  91. {    defaults to '=:Network Processor@*' }
  92.  
  93. function NlSetSearch (NlName, NlType, NlZone : Str32) : OSErr;
  94.  
  95. {    start/stop of NL task }
  96.  
  97. function NlStart : OSErr;
  98. function NlStop : OSErr;
  99.  
  100. function NlTask : OSErr;        { call this function periodically }
  101. function NlGetSleep : longint;    { time that may elapse until next call to NlTask  }
  102.  
  103. function NlCount : integer;        { or OSErr, if error, NlCount returns the number of partners found. }
  104. function NLActive (who:longint) : boolean;    { is who still on the list ? }
  105. function NLRandom : longint;    { any partner. returns 0 on error.}
  106. function NLNext(after:longint) : longint;    { next partner. NLNext(0) returns first. returns 0 on error. }
  107.  
  108. {$ENDC}
  109.  
  110. {$IFC NlServer}
  111.  
  112. {    register a server, pass '' to use choosername, only one entity can be registered }
  113.  
  114. function NlRegister (NlName, NlType : Str32) : OSErr;
  115. function NlDeregister : OSErr;
  116.  
  117. {$ENDC}
  118.  
  119. { Initialization. Call NlInit before using any of the other functions in this unit. }
  120.  
  121. function NlInit : OSErr;
  122.  
  123. { this function is obsolete and should no longer be used.
  124. function NlExit : OSErr;
  125. }
  126.  
  127. {$SETC UsingIncludes:=NetWorkLookupIncludes}
  128. {$ENDC}
  129.  
  130. implementation
  131.  
  132. {$R-} { we are indexing dynamic arrays outside of their declared limits }
  133.  
  134. {    =============================================================    }
  135.  
  136. {    name lookup - identication of possible partners }
  137.  
  138. const
  139.  
  140.     AppletalkTransportID = 'NetA';
  141. {$IFC NlClient}    
  142.     NlNEntities = 20;            { preallocate buffer space for # entities }
  143.     NlReserve    = 3;            { always allow for three more entries than we 
  144.                                     already know about }
  145.  
  146.     NlTimeOut = 2*60*60;        { 2 minutes }
  147.     NlUnused = 0;
  148.  
  149. type
  150.     NlRecord = record
  151.         Address : longint;
  152.         Ticks : longint;        { last successful lookup }
  153. (*        SystemFlag : longint;   { reserved. capas flag word}
  154.         nProcessor : longint;   { reserved. additional processors, if any. low=count, high=quality}
  155. *)
  156.     end;
  157.         
  158.     NlArray        = array [1..1] of NlRecord; { dynamically sized }
  159.     NlPtr        = ^NlArray;
  160.     NlHandle    = ^NlPtr;
  161.  
  162. var
  163.     NlEntityName : EntityName;    { entity to search for }
  164.     Nlnbppb : MPPParamBlock;    { lookup parameter block }
  165.     NlTicks : longint;            { ticks of last nltask }
  166.     NlBuffer : Ptr;                { replies we got } { Ptr (-1) if Nl cannot be used }
  167.     NlnbpIndex : integer;        { the reply we looked at last }
  168.     NlElements : integer;        { number of elements in list - including 0s }
  169.     NlStarted : longint;        { start of lookup process in ticks }
  170.     NlNames        : NlHandle;        { points to array of partners - NIL if NL task not active }
  171.     NlNodeCache : longint;        { avoid calls to driver }
  172. {$ENDC}
  173.  
  174. {$IFC NlServer}
  175. var
  176.     NlNTE : NamesTableEntry; 
  177.     NlNTEUsed : boolean;
  178. {$ENDC}
  179.  
  180. {    =============================================================    }
  181.  
  182. {    name lookup - identication of possible partners }
  183.  
  184. { this function returns 0 if appletalk is down or driver/appletalk transport not installed }
  185.  
  186. function NlNode : longint;
  187. var i, err : integer; p : TransportPtr;
  188. begin
  189.     i := 0;
  190.     repeat
  191.         err := GetTransport (p, i); i := i + 1;
  192.     until (err <> noErr) | (p^.TransportID = longint (AppletalkTransportID));
  193.     if err = noErr then NlNode := p^.TransportAddr
  194.     else NlNode := 0;
  195. end;
  196.  
  197. {$IFC NlServer}
  198.  
  199. function NlRegister (NlName, NlType : Str32) : OSErr;
  200. var lappb : MPPParamBlock; a : longint;
  201. begin
  202.     a := NlNode;
  203.     if (a = 0) then NlRegister := nlAtkOffErr
  204.     else if NlNTEUsed then NlRegister := NlDupReg
  205.     else begin
  206.         if length (NlName) = 0 then NlName := GetString (-16096)^^;
  207.         NBPSetNTE (@NlNTE, NlName, NlType, '*', BAnd (a, $000000ff));
  208.         with lappb do begin
  209.             verifyFlag := 0; { don't check for duplicates -- should we ? }
  210.             entityPtr := @NlNTE;
  211.         end;
  212.         NlRegister := PRegisterName(@lappb, false);
  213.         NlNTEUsed := true;
  214.     end;
  215. end;
  216.  
  217. function NlDeregister : OSErr;
  218. var lappb : MPPParamBlock;
  219. begin
  220. {    if NlNode = 0 then NlDeRegister := nlTaskErr
  221.     else begin -- appletalk close will have removed the name, but remove it anyway... }{ }
  222.         with lappb do begin
  223.             entityPtr := @NlNTE.nteData [2];
  224.         end;
  225.         if NlNTEUsed then
  226.             NlDeregister := PRemoveName(@lappb, false)
  227.         else NlDeregister := nlNoReg;
  228.         NlNTEUsed := false;
  229. end;
  230. {$ENDC}
  231.  
  232. {$IFC NlClient}
  233. function NlSetSearch (NlName, NlType, NlZone : Str32) : OSErr;
  234. begin
  235.     if (NlNames <> nil) then NlSetSearch := nlTaskErr { lookup task active }
  236.     else begin
  237.         NlSetSearch := noErr;
  238.         NBPSetEntity(@NlEntityName, NlName, NlType, NlZone);
  239.     end;
  240. end;
  241.         
  242. function NbpStart (entitycount : integer) : OSErr;
  243. var buffsize : longint;
  244. begin
  245.     NlNodeCache := NlNode;
  246.     buffsize := sizeof (NamesTableEntry) * (entitycount + NLReserve);
  247.     NlBuffer := NewPtr (buffsize);
  248.     if NlBuffer = nil then NbpStart := MemError
  249.     else begin
  250.         with Nlnbppb do begin
  251.             ioCompletion := nil;
  252.             if NlStarted - TickCount < 180 then
  253.                 interval := 20    { 20 seconds interval }
  254.             else
  255.                 interval := 60; { 60 seconds interval }
  256.             count := 1;     { retries done separateley }
  257.             entityPtr := @NlEntityName;
  258.             retBuffPtr := NlBuffer;
  259.             retBuffSize := buffsize;
  260.             maxToGet := entitycount;{ approx responses - should be maxint }
  261.         end;
  262.         NbpStart := PLookUpName (@Nlnbppb, true);
  263.     end;
  264. end;
  265.  
  266. function NbpStop : OSErr;
  267. var buffsize : longint; nbppb : MPPParamBlock; err : integer;
  268. begin
  269.     NbpStop := noErr;
  270.     if NlNbppb.ioresult > 0 then begin
  271.         with nbppb do nKillQEl := @NlNbppb;
  272.         err := PKillNBP (@nbppb, false);
  273.         if err = controlErr then { cannot abort, must wait for completion - appletalk version < 48 }
  274.             repeat
  275.                 err := NlNbppb.ioresult;
  276.             until err <= noErr;
  277.         NbpStop := err;
  278.     end;
  279.     DisposPtr (NlBuffer); NlBuffer := nil;
  280. end;
  281.  
  282. function NlStart : OSErr;
  283. var err : OSErr; 
  284.     mppdce : DCtlHandle; 
  285. begin
  286.     if (NlBuffer <> nil) then NlStart := nlTaskErr { already active }
  287.     else begin
  288.         err := ATPLoad; { ignore error }
  289.     (*    mppdce := GetDCtlEntry (-10); { .MPP }
  290.         if (mppdce = nil) | (Ptr (longint (@mppdce^^.dCtlQHdr) +1)^ < 48) then
  291.             err := nlVersion
  292.         else *) begin
  293.             NlnbpIndex := 1; NlStarted := TickCount; NlElements := 0;
  294.             NlNames := NlHandle (NewHandleClear (sizeof (NlRecord) * NlNEntities));
  295.             if NlNames = nil then err := MemError
  296.             else begin
  297.                 err := NbpStart (NlNEntities);
  298.                 if err = notOpenErr then
  299.                     err := noErr; { automatically restarted when AppleTalk is turned on }
  300.             end;
  301.         end;
  302.     end;
  303.     if err < 0 then NlStart := err else NlStart := noErr; { compensate for A/UX returning 1 }
  304. end;
  305.  
  306. function NlStop : OSErr;
  307. var err : integer;
  308. begin
  309.     if (NlBuffer = nil) then err := nlTaskErr { not active }
  310.     else begin
  311.         err := NbpStop; NlElements := nlTaskErr;
  312.         DisposHandle (Handle (NlNames)); NlNames := nil;
  313.     end;
  314.     NlStop := err;
  315. end;
  316.  
  317. function NlGetSleep : longint;
  318. var sleep : longint;
  319. begin
  320.     if (NlBuffer = nil) then sleep := maxlongint { no time required at all }
  321.     else sleep := NlTicks + 300 - TickCount; { once every five seconds is always enough }
  322.     if sleep < 0 then sleep := 0;
  323.     NlGetSleep := sleep;
  324. end;
  325.  
  326. {    NlTask updates the information in NlNames based upon responses to the 
  327.     most recent async name lookup. If the name lookup timed out, a new is 
  328.     initiated. The ticks valus in names is updated for all entities found. 
  329.     If new entities are found, they replace records with an address of 0. 
  330.     If new entries are found, the handle is enlarged. Call this routine 
  331.     during idle time or whenever new entities may be useful. }
  332.  
  333. function NlTask : OSErr;
  334.  
  335. var err : OSErr;
  336.     entity : EntityName;
  337.     a : AddrBlock;
  338.     p, q : NlPtr; i, n : integer;
  339.     l : longint;
  340. begin
  341.     if (NlBuffer = nil) then err := noErr
  342.     else if (NlBuffer = Ptr (-1)) then err := nlTaskErr 
  343.     else begin
  344.         NlTicks := TickCount; err := noErr;
  345.         while (err = noErr) and (NlnbpIndex <= NlNbppb.numGotten) do 
  346.         if not IsMPPOpen then begin
  347.             NlNbpPb.ioresult := notOpenErr;
  348.             err := NbpStop
  349.         end
  350.         else begin
  351.             err := NBPExtract (NlBuffer, NlNbppb.numGotten, NlnbpIndex, entity, a);
  352.             if err <> noErr then CheckError ('NBPExtract returned error', err) { never }
  353.             else begin
  354.                 NlnbpIndex := NlnbpIndex + 1;
  355.                 if longint (a) <> NlNodeCache then begin { don't include ourself in list }
  356.                     n := NlElements; p := NlNames^; q := nil;
  357.                     while n > 0 do begin
  358.                         if longint (p^[n].Address) = longint (a) then n := -1 { stop search }
  359.                         else n := n - 1;
  360.                     end;
  361.                     if n = 0 then begin{ not found, add }
  362.                         l := GetHandleSize (Handle (NlNames)); n := l div sizeof (NlRecord);
  363.                         if n <= NlElements then begin
  364.                             SetHandleSize (Handle (NlNames), l + sizeof (NlRecord) * NlReserve);
  365.                             err := MemError;
  366.                         end;
  367.                         if err = noErr then begin { avail position at end of list }
  368.                             NlElements := NlElements + 1;
  369.                             with NlNames^^ [NlElements] do begin
  370.                                 Address := longint (a); Ticks := NlTicks;
  371.                             end
  372.                         end;
  373.                     end;
  374.                 end;
  375.             end;
  376.         end; 
  377.         { while (err = noErr) and (NlnbpIndex <= NlNbppb.nbpDataField) do  }
  378.  
  379.         if (err = noErr) and (NlNbpPb.ioresult <= 0) then begin { restart }
  380.             err := NbpStop; NlnbpIndex := 1;
  381.             n := NlElements;
  382.             if n < NlNEntities then n := NlNEntities;
  383.             if err = noErr then err := NbpStart (n);
  384.  
  385.             l := NlTicks - NlTimeout;            { added 21-10-89 , modified 31-10-89 }
  386.             n := 1; i := 1; p := NlNames^;        { note that we preserve order to allow }
  387.             while n <= NlElements do            { round robin fashion }
  388.             with p^ [n] do 
  389.             if Ticks < l then n := n + 1 { skip, don´t copy }
  390.             else begin
  391.                 if i <> n then p^[i] := p^[n];
  392.                 i := i + 1; n := n + 1;
  393.             end;
  394.             NlElements := i - 1;        
  395.         end;
  396.     end;
  397.     NlTask := err;
  398. end;
  399.  
  400. function NlCount : integer;
  401. var i, n : integer; l : longint;
  402.     p : NlPtr;
  403. begin
  404.     NlCount := NlElements;
  405. end;
  406.     
  407. function NlIndex (address : longint) : integer; { or OSErr, if error }
  408. var n : integer;
  409.     p : NlPtr;
  410. begin
  411.     if NlNames = nil then NlIndex := nlTaskErr
  412.     else begin
  413.         n := NlElements; p := NlNames^;
  414.         while (n > 0) & (p^[n].Address <> address) do n := n - 1;
  415.         if n = 0 then NlIndex := nlNotFound
  416.         else NlIndex := n;
  417.     end
  418. end;
  419.  
  420. function NLActive(who:longint):boolean;
  421. var scr:integer;
  422. begin
  423.     NLActive:=false; {default}
  424.      if NlCount>0 then begin
  425.      NLActive:=(NLIndex(who)>0);
  426.      end;
  427. end;
  428.  
  429. {    random questionable, because the modulus may change }
  430.  
  431. function NLRandom:longint;
  432. var NrOthers,scr1:integer;
  433. begin
  434.     scr1 := NlTask; { update table }
  435.     NrOthers := NlElements; 
  436.     if NrOthers < 1 then NLRandom:=0 else begin 
  437.         scr1:=abs(random mod NrOthers) + 1;
  438.         {•••••••• random uses a5 ••••••••••••••••••}
  439.         NLRandom:=NlNames^^[scr1].Address;
  440.     end;
  441. end;
  442.  
  443. {    this function could be improved to cache the last index }
  444.  
  445. function NLNext(after:longint):longint;
  446. var scr,NrOthers:integer;
  447. begin
  448.     scr := NlTask; { update table }
  449.     NrOthers:=NlElements;
  450.     if after=0 then scr:=1 else scr:=NLindex(after)+1;
  451.     if (NrOthers < 1) or (scr<0) then NLNext:=0 else begin 
  452.         if scr>NrOthers then scr:=1;
  453.         NLNext:= NlNames^^[scr].Address;
  454.     end;
  455. end;
  456. {$ENDC}
  457.  
  458. {    =============================================================    }
  459.  
  460. {    event patch }
  461.  
  462. {$Z+} {export symbols}
  463.  
  464. function EventPatch (var ev : EventRecord) : boolean;
  465. var err : integer; saveda5 : longint;
  466. begin
  467.     saveda5 := SetCurrentA5;
  468. {$IFC NlClient}
  469.     if NlNames <> nil then err := NlTask;
  470. {$ENDC}
  471.     savedA5 := SetA5 (savedA5);
  472. end;
  473. {$Z-} {export symbols}
  474.  
  475. {    =============================================================    }
  476.  
  477. {    initialization and termination }
  478.  
  479. procedure InstallPatches;
  480. external;
  481. procedure UnInstallPatches;
  482. external;
  483.  
  484.  
  485. function NlExit : OSErr;
  486. begin
  487.     NlExit := noErr;
  488. {$IFC NlClient}
  489.     if Nlbuffer <> nil then CheckError ('ExitNameLookup', NlStop);
  490. {$ENDC}
  491. {$IFC NlServer}
  492.     if NlNTEUsed then CheckError ('NlDeregister', NlDeregister);
  493. {$ENDC}
  494.     UninstallPatches;
  495. end;
  496.  
  497. {$Z+} {export symbols}
  498. procedure ExitPatch;
  499. var e : integer; saveda5 : longint;
  500. begin
  501.     saveda5 := SetCurrentA5;
  502.     e := NlExit;
  503.     savedA5 := SetA5 (savedA5);
  504. end;
  505. {$Z-} {export symbols}
  506.  
  507. function NlInit : OSErr;
  508. begin
  509.     NlInit := noErr;
  510.     InstallPatches;
  511. {$IFC NlServer}
  512.     NlNTEUsed := false; 
  513. {$ENDC}
  514. {$IFC NlClient}
  515.     NlNames := nil; NlBuffer := nil; NlElements := nlTaskErr;
  516.     CheckError ('set search', NlSetSearch ('=', 'Network Processor', '*'));
  517. {$ENDC}
  518. end;
  519.  
  520. end.
  521.